#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/timekeeping.h>
#include <linux/etherdevice.h>
#include <linux/netdevice.h>
#include <linux/gpio.h>
#include <linux/etherdevice.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include "esp_wifi.h"

volatile u8 stop_data = 0;
struct esp_adapter 	adapter;
#define ESP_LINK_DOWN			0

static int esp_open(struct net_device *ndev);
static int esp_stop(struct net_device *ndev);
static int esp_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev);
static int esp_set_mac_address(struct net_device *ndev, void *addr);
static void esp_tx_timeout(struct net_device *ndev);
static struct net_device_stats* esp_get_stats(struct net_device *ndev);
static void esp_set_rx_mode(struct net_device *ndev);
int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size);

static const struct net_device_ops esp_netdev_ops = {
	.ndo_open = esp_open,
	.ndo_stop = esp_stop,
	.ndo_start_xmit = esp_hard_start_xmit,
	.ndo_set_mac_address = esp_set_mac_address,
	.ndo_validate_addr = eth_validate_addr,
	.ndo_tx_timeout = esp_tx_timeout,
	.ndo_get_stats = esp_get_stats,
	.ndo_set_rx_mode = esp_set_rx_mode,
};

static struct net_device_stats* esp_get_stats(struct net_device *ndev)
{
	struct esp_private *priv = netdev_priv(ndev);
	return &priv->stats;
}

static int esp_set_mac_address(struct net_device *ndev, void *data)
{
	struct esp_private *priv = netdev_priv(ndev);
	struct sockaddr *mac_addr = data;

	if (!priv)
		return -EINVAL;

	ether_addr_copy(priv->mac_address, mac_addr->sa_data);
	ether_addr_copy(ndev->dev_addr, mac_addr->sa_data);
	return 0;
}

static void esp_tx_timeout(struct net_device *ndev)
{
}

static void esp_set_rx_mode(struct net_device *ndev)
{
}

static int esp_open(struct net_device *ndev)
{
	netif_start_queue(ndev);
	return 0;
}

static int esp_stop(struct net_device *ndev)
{
	netif_stop_queue(ndev);
	return 0;
}

static int esp_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)  
{  
    struct sk_buff *new_skb;  // 声明一个新的 sk_buff 指针，用于可能的缓冲区重分配  
    struct esp_private *priv = netdev_priv(ndev);  // 获取与网络设备 ndev 关联的私有结构体的指针  
    struct esp_skb_cb *cb; // 声明指向 sk_buff 中控制块的指针  

    // 检查私有数据是否有效  
    if (!priv) {  
        dev_kfree_skb(skb);  // 若 priv 无效，则释放 skb 内存  
        return -EINVAL;      // 返回无效参数错误  
    }  
    
    // 检查 skb 的长度是否合法  
    if (!skb->len || (skb->len > ETH_FRAME_LEN)) {  
        // 打印错误信息，表明 skb 的长度不正确  
        printk (KERN_ERR "%s: Bad len %d\n", __func__, skb->len);  
        priv->stats.tx_dropped++; // 统计发送丢包数  
        dev_kfree_skb(skb);      // 释放 skb 内存  
        return -EINVAL;          // 返回无效参数错误  
    }  

    // 检查 skb 的头部空间是否足够  
    if (skb_headroom(skb) < ESP_PAYLOAD_HEADER) {  
        // 不足空间则重新分配 skb，增加头部空间  
        new_skb = skb_realloc_headroom(skb, ESP_PAYLOAD_HEADER);  

        // 检查新分配的 skb 是否为 NULL  
        if (unlikely(!new_skb)) {  
            printk (KERN_ERR "%s: Failed to allocate SKB\n", __func__);  
            priv->stats.tx_dropped++; // 统计发送丢包数  
            dev_kfree_skb(skb);      // 释放 skb 内存  
            return -ENOMEM;          // 返回内存不足错误  
        }  

        // 释放旧的 skb  
        dev_kfree_skb(skb);   
        // 更新 skb 指针为新的分配的 skb  
        skb = new_skb;  
    }  

    // 获取 skb 中的控制块，将私有数据指针赋值给控制块  
    cb = (struct esp_skb_cb *) skb->cb;   
    cb->priv = priv;  // 存储私有数据指针以供后续使用  

    // 将 skb 添加到发送队列的尾部  
    skb_queue_tail(&adapter.tx_q, skb);  
    // 增加等待发送的 skb 数量  
    atomic_inc(&adapter.tx_pending);      
    // 提交工作到工作队列，以异步方式进行发送处理  
    queue_work(adapter.tx_workqueue, &adapter.tx_work);   

    return 0; // 正常返回，发送准备就绪  
}  

static int esp_init_net_dev(struct net_device *ndev, struct esp_private *priv)
{
	int ret = 0;
	/* Set netdev */
/*	SET_NETDEVesp_init_net_dev_DEV(ndev, &adapter->context.func->dev);*/

	/* set net dev ops */
	ndev->netdev_ops = &esp_netdev_ops;

	ether_addr_copy(ndev->dev_addr, priv->mac_address);
	/* set ethtool ops */

	/* update features supported */

	/* min mtu */

	/* register netdev */
	ret = register_netdev(ndev);

/*	netif_start_queue(ndev);*/
	/* ndev->needs_free_netdev = true; */

	/* set watchdog timeout */

	return ret;
}

static void esp_remove_network_interfaces(struct esp_adapter *adapter)
{
	if (adapter->priv[0]->ndev) {
		netif_stop_queue(adapter->priv[0]->ndev);
		unregister_netdev(adapter->priv[0]->ndev);
		free_netdev(adapter->priv[0]->ndev);
	}

	if (adapter->priv[1]->ndev) {
		netif_stop_queue(adapter->priv[1]->ndev);
		unregister_netdev(adapter->priv[1]->ndev);
		free_netdev(adapter->priv[1]->ndev);
	}
}


static int insert_priv_to_adapter(struct esp_private *priv)
{
	int i = 0;

	for (i = 0; i < ESP_MAX_INTERFACE; i++) {
		/* Check if priv can be added */
		if (adapter.priv[i] == NULL) {
			adapter.priv[i] = priv;
			return 0;
		}
	}

	return -1;
}

static int esp_init_priv(struct esp_private *priv, struct net_device *dev,
		u8 if_type, u8 if_num)
{
	int ret = 0;

	if (!priv || !dev)
		return -EINVAL;

	ret = insert_priv_to_adapter(priv);
	if (ret)
		return ret;

	priv->ndev = dev;
	priv->if_type = if_type;
	priv->if_num = if_num;
	priv->link_state = ESP_LINK_DOWN;
	priv->adapter = &adapter;
	memset(&priv->stats, 0, sizeof(priv->stats));

	return 0;
}


static int esp_add_interface(struct esp_adapter *adapter, u8 if_type, u8 if_num, char *name)
{
	struct net_device *ndev = NULL;
	struct esp_private *priv = NULL;
	int ret = 0;

	ndev = alloc_netdev_mqs(sizeof(struct esp_private), name,
			NET_NAME_ENUM, ether_setup, 1, 1);

	if (!ndev) {
		printk(KERN_ERR "%s: alloc failed\n", __func__);
		return -ENOMEM;
	}

	priv = netdev_priv(ndev);

	/* Init priv */
	ret = esp_init_priv(priv, ndev, if_type, if_num);
	if (ret) {
		printk(KERN_ERR "%s: Init priv failed\n", __func__);
		goto error_exit;
	}

	ret = esp_init_net_dev(ndev, priv);
	if (ret) {
		printk(KERN_ERR "%s: Init netdev failed\n", __func__);
		goto error_exit;
	}

	return ret;

error_exit:
	free_netdev(ndev);
	return ret;
}

static void flush_ring_buffers(struct esp_adapter *adapter)
{
	struct sk_buff *skb;

	printk (KERN_INFO "%s: Flush Pending SKBs: %d %d\n", __func__,
			atomic_read(&adapter->tx_pending),
			atomic_read(&adapter->rx_pending));

	while ((skb = skb_dequeue(&adapter->tx_q))) {
		dev_kfree_skb_any(skb);
		atomic_dec(&adapter->tx_pending);
	}

	while ((skb = skb_dequeue(&adapter->rx_q))) {
		dev_kfree_skb_any(skb);
		atomic_dec(&adapter->rx_pending);
	}
}

int esp_remove_card(struct esp_adapter *adapter)
{
	stop_data = 1;

	if (!adapter)
		return 0;

	/* Flush workqueues */
	if (adapter->if_rx_workqueue)
		flush_workqueue(adapter->if_rx_workqueue);

	if (adapter->tx_workqueue)
		flush_workqueue(adapter->tx_workqueue);

	esp_remove_network_interfaces(adapter);

	flush_ring_buffers(adapter);

	adapter->priv[0] = NULL;
	adapter->priv[1] = NULL;

	atomic_set(&adapter->tx_pending, 0);
	atomic_set(&adapter->rx_pending, 0);

	return 0;
}
EXPORT_SYMBOL(esp_remove_card);

int esp_add_card(struct esp_adapter *adapter)
{
	int ret = 0;

	if (!adapter) {
		printk(KERN_ERR "%s: Invalid args\n", __func__);
		return -EINVAL;
	}

	stop_data = 0;

	/* Add interface STA and AP */
	ret = esp_add_interface(adapter, ESP_STA_IF, 0, "ethsta%d");
	if (ret) {
		printk(KERN_ERR "%s: Failed to add STA\n", __func__);
		return ret;
	}

	ret = esp_add_interface(adapter, ESP_AP_IF, 0, "ethap%d");
	if (ret) {
		printk(KERN_ERR "%s: Failed to add AP\n", __func__);
		esp_remove_network_interfaces(adapter);
	}

	return ret;
}
EXPORT_SYMBOL(esp_add_card);

void esp_process_new_packet_intr(struct esp_adapter *adapter)
{
	// printk("1111111111111111\n");
	if(adapter)
		queue_work(adapter->if_rx_workqueue, &adapter->if_rx_work);
}

EXPORT_SYMBOL(esp_process_new_packet_intr);

struct sk_buff * esp_alloc_skb(u32 len)
{
	struct sk_buff *skb;

	skb = netdev_alloc_skb(NULL, len);
	return skb;
}
EXPORT_SYMBOL(esp_alloc_skb);

static struct esp_private * get_priv_from_payload_header(struct esp_payload_header *header)
{
	struct esp_private *priv;
	u8 i;

	if (!header)
		return NULL;

	for (i = 0; i < ESP_MAX_INTERFACE; i++) {
		priv = adapter.priv[i];

		if (!priv)
			continue;

		if (priv->if_type == header->if_type &&
				priv->if_num == header->if_num) {
			return priv;
		}
	}

	return NULL;
}

#define DUMP_PREFIX_NONE 0  
#define DUMP_PREFIX_ADDRESS 1  
#define DUMP_PREFIX_OFFSET 2  

void print_hex_dump_bytes(const char *prefix_str, int prefix_type,  
                           const void *buf, size_t len) {  
    const unsigned char *data = (const unsigned char *)buf;  
    
    size_t i;  
    size_t j; // 在这里提前声明 j  
    size_t total_rows = (len + 15) / 16; // 每行 16 字节  

    for (i = 0; i < total_rows; i++) {  
        // 打印前缀  
        switch (prefix_type) {  
            case DUMP_PREFIX_ADDRESS:  
                printk("%s0x%04zx: ", prefix_str, i * 16);  
                break;  
            case DUMP_PREFIX_OFFSET:  
                printk("%s[%04zx]: ", prefix_str, i * 16);  
                break;  
            default:  
                printk("%s", prefix_str);  
                break;  
        }  

        // 打印每行的 16 字节  
        for (j = 0; j < 16; j++) { // 在这里使用之前声明的 j  
            size_t index = i * 16 + j;  
            if (index < len) {  
                printk("%02x ", data[index]);  
            } else {  
                printk("   "); // 填充不足 16 字节的输出  
            }  
        }  

        // 打印 ASCII 值  
        printk(" |");  
        for (j = 0; j < 16; j++) { // 在这里重新使用 j  
            size_t index = i * 16 + j;  
            if (index < len) {  
                unsigned char c = data[index];  
                printk("%c", (c >= 32 && c < 127) ? c : '.');  
            }  
        }  
        printk("|\n");  
    }  
} 

static void process_rx_packet(struct sk_buff *skb)
{
	struct esp_private *priv;
    /* 传输协议头 */
	struct esp_payload_header *payload_header;
	u16 len, offset;
	// struct hci_dev *hdev = adapter.hcidev;
	// u8 *type;

	if (!skb)
		return;

	/* get the paload header */
	payload_header = (struct esp_payload_header *) skb->data;

	len = le16_to_cpu(payload_header->len);
	offset = le16_to_cpu(payload_header->offset);
	// printk("len = [%d] offset [%d] [payload_header->if_type = [%d]]\n", len, offset, payload_header->if_type);

	if (payload_header->if_type == ESP_SERIAL_IF) {
// #ifdef CONFIG_SUPPORT_ESP_SERIAL
// 		esp_serial_data_received(payload_header->if_num, skb->data + offset, len);
// #else
// 		printk(KERN_ERR "Dropping unsupported serial frame\n");
// #endif
		// dev_kfree_skb_any(skb);
	} else if (payload_header->if_type == ESP_STA_IF || payload_header->if_type == ESP_AP_IF) {
		/* chop off the header from skb */

		skb_pull(skb, offset);

		/* retrieve priv based on payload header contents */
		priv = get_priv_from_payload_header(payload_header);

		if (!priv) {
			printk (KERN_ERR "%s: empty priv\n", __func__);
			dev_kfree_skb_any(skb);
/*			atomic_dec(&adapter.rx_pending);*/
			return;
		}

		skb->dev = priv->ndev;
		skb->protocol = eth_type_trans(skb, priv->ndev);
		// printk("skb_pull [%s]\n", (char *)skb->data);
		skb->ip_summed = CHECKSUM_NONE;
		
		// print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, skb->data, skb->len);
		// printk("len = [%d]\n", skb->len);
		// printk("skb_pull after[%s]\n", (char *)skb->data);
		/* Forward skb to kernel */
		netif_rx(skb);
		priv->stats.rx_bytes += skb->len;
		priv->stats.rx_packets++;
	} else if (payload_header->if_type == ESP_HCI_IF) {
// 		if (hdev) {
// 			/* chop off the header from skb */
// 			skb_pull(skb, offset);

// /*			print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, skb->data, skb->len);*/
// 			type = skb->data;
// 			hci_skb_pkt_type(skb) = *type;
// 			skb_pull(skb, 1);

// 			if (hci_recv_frame(hdev, skb)) {
// 				hdev->stat.err_rx++;
// 			} else {
// 				esp_hci_update_rx_counter(hdev, *type, skb->len);
// 			}
// 		}
	}
}

int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size)
{
	if (!adapter || !adapter->if_ops || !adapter->if_ops->write)
		return -EINVAL;

	return adapter->if_ops->write(adapter, buf, size);
}


static void process_tx_packet (void)
{
	struct sk_buff *skb;
	struct esp_private *priv;
	struct esp_skb_cb *cb;
	struct esp_payload_header *payload_header;
	struct sk_buff *new_skb;
	int ret = 0;
	u8 pad_len = 0;
	u16 len = 0;
	static u32 c = 0;

	while ((skb = skb_dequeue(&adapter.tx_q))) {
		c++;
		/* Get the priv */
		cb = (struct esp_skb_cb *) skb->cb;
		priv = cb->priv;

		if (!priv) {
			dev_kfree_skb_any(skb);
			atomic_dec(&adapter.tx_pending);
			continue;
		}

		len = skb->len;

		/* Create space for payload header */
		pad_len = sizeof(struct esp_payload_header);

		if (skb_headroom(skb) < pad_len) {
			/* insufficent headroom to add payload header */
			new_skb = skb_realloc_headroom(skb, pad_len);

			if(!new_skb) {
				printk(KERN_ERR "%s: Failed to allocate SKB", __func__);
				dev_kfree_skb(skb);
				atomic_dec(&adapter.tx_pending);
				continue;
			}

			dev_kfree_skb(skb);

			skb = new_skb;
		}

		skb_push(skb, pad_len);

		/* Set payload header */
		payload_header = (struct esp_payload_header *) skb->data;
		memset(payload_header, 0, pad_len);

		payload_header->if_type = priv->if_type;
		payload_header->if_num = priv->if_num;
		payload_header->len = cpu_to_le16(skb->len - pad_len);
		payload_header->offset = cpu_to_le16(pad_len);
		payload_header->reserved1 = c % 255;

/*		printk (KERN_ERR "H -> S: %d %d %d %d", len, payload_header->offset,*/
/*				payload_header->len, payload_header->reserved1);*/

		if (!stop_data) {
			ret = esp_send_packet(priv->adapter, skb->data, skb->len);

			if (ret) {
				priv->stats.tx_errors++;
			} else {
				priv->stats.tx_packets++;
				priv->stats.tx_bytes += skb->len;
			}
		} else {
			priv->stats.tx_dropped++;
		}

		dev_kfree_skb_any(skb);
		atomic_dec(&adapter.tx_pending);
	}
}

static void esp_tx_work (struct work_struct *work)
{
	process_tx_packet();
}

static int esp_get_packets(struct esp_adapter *adapter)
{
	struct sk_buff *skb;

	if (!adapter || !adapter->if_ops || !adapter->if_ops->read)
		return -EINVAL;

	skb = adapter->if_ops->read(adapter);

	if (!skb)
		return -EFAULT;

	process_rx_packet(skb);

	return 0;
}

static void esp_if_rx_work (struct work_struct *work)
{
	/* read inbound packet and forward it to network/serial interface */
	// printk("34567898764\n");
	esp_get_packets(&adapter);
}

static void deinit_adapter(void)
{
	if (adapter.if_rx_workqueue)
		destroy_workqueue(adapter.if_rx_workqueue);

	if (adapter.tx_workqueue)
		destroy_workqueue(adapter.tx_workqueue);
}

static struct esp_adapter * init_adapter(void)
{

	memset(&adapter, 0, sizeof(adapter));

	/* Prepare interface RX work */
	adapter.if_rx_workqueue = create_workqueue("ESP_IF_RX_WORK_QUEUE");

	if (!adapter.if_rx_workqueue) {
		deinit_adapter();
		return NULL;
	}

	INIT_WORK(&adapter.if_rx_work, esp_if_rx_work);

	/* Prepare TX work */
	adapter.tx_workqueue = create_workqueue("ESP_TX_WORK_QUEUE");

	if (!adapter.tx_workqueue) {
		deinit_adapter();
		return NULL;
	}

	INIT_WORK(&adapter.tx_work, esp_tx_work);

	/* Prepare TX work */
	skb_queue_head_init(&adapter.tx_q);
	skb_queue_head_init(&adapter.rx_q);

	atomic_set(&adapter.tx_pending, 0);
	atomic_set(&adapter.rx_pending, 0);

	return &adapter;
}

static int __init esp_init(void)
{
    int ret = 0;

    struct esp_adapter	*adapter;

    /* 初始化适配器*/
    adapter = init_adapter();
	
    if(!adapter)
    {
        return -EFAULT;
    }

    // /* Init transport layer */
	ret = esp_init_interface_layer(adapter);

	if (ret != 0) {
		deinit_adapter();
	}
	
    
    return 0;
}

static void __exit esp_exit(void)
{
	esp_deinit_interface_layer();
	deinit_adapter();
}


module_init(esp_init);
module_exit(esp_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lql");